package org.thirdHero.core.token;

import org.springframework.stereotype.Service;
import org.thirdHero.core.constant.CommonConstant;
import org.thirdHero.core.enums.ResultEnum;
import org.thirdHero.core.exception.TokenErrorException;
import org.thirdHero.core.util.DateHelper;
import org.thirdHero.core.util.ReflectUtils;
import org.thirdHero.core.util.StringUtil;
import org.thirdHero.core.util.RedisUtil;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Map;

@Service
public class UserTokenManager {
    @Resource
    private RedisUtil redisUtil;

    private static final ThreadLocal<Map<String, UserToken>> tokenMap = new ThreadLocal<>();
    private static final ThreadLocal<Map<String, UserToken>> idMap = new ThreadLocal<>();

    /**
     * 根据token获得用户唯一标示
     * @param token
     * @return
     */
    public  String getUserId(String token) {
        Object o = redisUtil.get(token);
        if(o==null){
            return null;
        }
        UserToken userToken = (UserToken) o;

        if(userToken.getExpireTime().isBefore(LocalDateTime.now())){
            redisUtil.del(userToken.getUserId());
            redisUtil.del(userToken.getUserId().concat(CommonConstant.SESSION_USER));
            return null;
        }
        return userToken.getUserId();
    }

    public  UserToken generateToken(String id,Object user){
        UserToken userToken = null;

        String token = CommonConstant.WX_MINI_TOKEN_APP + StringUtil.getUUID();

        LocalDateTime update = LocalDateTime.now();
        LocalDateTime expire = update.plusDays(30);

        userToken = new UserToken();
        userToken.setToken(token);
        userToken.setUpdateTime(update);
        userToken.setExpireTime(expire);
        userToken.setUserId(id);
        userToken.setUser(user);
        redisUtil.set(token,userToken);
        return userToken;
    }

    /**
     * 获取缓存中存储的用户信息
     * @param token
     * @return
     */
    public   Object getSessionUser(String token){
        if(!redisUtil.hasKey(token)){
            throw  new TokenErrorException(ResultEnum.ERROR_TOKEN_EMPTY);
        }
        UserToken userToken =  convertAccessToken(redisUtil.get(token));
        if(userToken.getExpireTime().isBefore(LocalDateTime.now())){
            throw new TokenErrorException(ResultEnum.ERROR_TOKEN_TIME_OUT);
        }
        Object user = userToken.getUser();
        return user;
    }
    /**
     * 反射转换：解决因类加载器不同导致的转换异常
     */
    private UserToken convertAccessToken(Object redisObject){
        UserToken at = new UserToken();
        at.setToken(ReflectUtils.getFieldValue(redisObject,"token")+"");
        at.setUserId(ReflectUtils.getFieldValue(redisObject,"userId")+"");
        at.setUser(ReflectUtils.getFieldValue(redisObject,"user"));
        at.setExpireTime(DateHelper.str2LocalDateTime(ReflectUtils.getFieldValue(redisObject,"expireTime")+""));
        at.setUpdateTime(DateHelper.str2LocalDateTime(ReflectUtils.getFieldValue(redisObject,"updateTime")+""));
        return at;
    }
}
